/**
 * 最优解
 * 动态规划
 * 算法视频: https://www.bilibili.com/video/BV18x411V7fm?spm_id_from=333.999.0.0
 */

class DynamicProgrammingUtils{


    /**
     *
     * @param dmsPostageActivities  活动列表  规则
     * @param sukList     商品列表  数据
     */
    constructor( dmsPostageActivities ,sukList) {

        this. prev=new ArrayList();//最优列表
         this.opt=new ArrayList();

         this.ids==new ArrayList(); //每层选中的活动列表

        this.dmsPostageActivities1= new ArrayList();

        //活动列表
        // id   总价  [ sukId1  sukId2 sukIdN]
        this. dmsPostageActivities =dmsPostageActivities;

        //订单
        //   [sukId  数量 单价 总价]
        this.  sukList=sukList;

        this.  optf();
    }


    /**
     * 获取 没有活动的sku
     * @return
     */
       findNoSku(){
        let sku = findPostageSku();
      let  omsCartItemDtos = ConvertUtils.sourceToTarget(this.sukList, OmsCartItemDto.class);
        omsCartItemDtos.removeAll(sku);
        return  omsCartItemDtos;

    }

    /**
     * 获取 活动的sku
     * @return
     */
        findPostageSku(){
        let  postageEntities = findPostage();
        let  list =new ArrayList ();
        postageEntities.forEach( postageEntities=>{
            list.addAll(postageEntity.getSukList());
        })
        return list;

    }


    /**
     * 获取 获取  活动列表
     * @return
     */
        findPostage(){
        if(this.ids.size()==0) return  new ArrayList ();

         let integers = this.ids.get(this.ids.size() - 1);

        let list = new ArrayList ();
        for(let i=0;i<integers.size();i++){
            list.add(dmsPostageActivities1.get(integers.get(i)));
        }

        return list;
    }


    /**
     * 最优解
     */
    //
   optf(){
        //获取每个sukId 可能的活动,全部组合
      this. dmsPostageActivities1 = allPossible(dmsPostageActivities, sukList);
        // 算法 计算 prev
        for(let  i=0;i <dmsPostageActivities1.size();i++){
            let  dmsPostageActivities2 = dmsPostageActivities1.get(i);
            prev.add(null);
            for(let  l=i-1;-1<l;l--){
                let   dmsPostageActivities3 = dmsPostageActivities1.get(l);
                if(!activityMutex(dmsPostageActivities2,dmsPostageActivities3)){
                    prev.set(i,l);
                    break;
                }
            }
        }

        for(let   i=0;i <dmsPostageActivities1.size();i++){
            let  dmsPostageActivities2 = dmsPostageActivities1.get(i);
            let aDouble = maxPrice(dmsPostageActivities2, i);
            opt.add(aDouble);
        }

    }




    /**
     * 获取 opt
     * @param postageEntity
     * @param i
     * @return
     */
      maxPrice(  postageEntity,  i){

        let objects = new ArrayList ();
        let objects1 = new ArrayList ();
        objects.add(i);
        if(prev.get(i)==null){
        this.ids.add(objects );
        return  postageEntity.getSukListTotal();
        }
        let dmsPostageActivities2 = this.dmsPostageActivities1.get(i);
        let sukListTotal = dmsPostageActivities2.getSukListTotal();
        if(prev.get(i) !=null){
            objects1.addAll( ids.get(prev.get(i)));
            objects1.add(i);
            if(prev.get(prev.get(i)) !=null){
                let sukListTotal1 = opt.get(prev.get(i));
                let add = BigDecimal.valueOf(sukListTotal).add(BigDecimal.valueOf(sukListTotal1));
                sukListTotal = add.doubleValue();
            }else {
                let dmsPostageActivities3=  this.dmsPostageActivities1.get(prev.get(i));
                let sukListTotal1 = dmsPostageActivities3.getSukListTotal();
                let add = BigDecimal.valueOf(sukListTotal).add(BigDecimal.valueOf(sukListTotal1));
                sukListTotal = add.doubleValue();
            }
        }

        if(postageEntity.getSukListTotal().doubleValue() >sukListTotal.doubleValue() ){
            this. ids.add(objects);
            return postageEntity.getSukListTotal().doubleValue();
        }else {
            this. ids.add(objects1);
            return  sukListTotal;
        }
    }


    /**
     * 全部活动 可能
     * @return
     */
   allPossible ( dmsPostageActivities, sukList){

        let  postageEntities = new ArrayList ();
        dmsPostageActivities.forEach (postageEntity => { //遍历活动
            let objects = new ArrayList ();
            let dmsPostageActivities2 = postageEntity.getDmsPostageActivities();

            sukList.forEach (omsCartItemDto => { // suk
                dmsPostageActivities2.forEach(dmsPostageActivities3 => {  // 活动分类

                    if(dmsPostageActivities3.getPrimaryCategoryId().equals(omsCartItemDto.getProductCategoryId()))
                    {
                        objects.add(omsCartItemDto);
                    }
                })
            })

            let  postageEntity1 = ConvertUtils.sourceToTarget(postageEntity, PostageEntity.class);

            postageEntity1.setSukList(objects);
            postageEntity1.setDmsPostageActivitiesRanges(postageEntity.getDmsPostageActivitiesRanges());
            postageEntities.add(postageEntity1);
        } )


        let  res = new ArrayList ();
        postageEntities.forEach(postageEntity => {
            res.addAll(postageLis(postageEntity));
        })


            return res;
    }

    //根据价格区间 返回可以可能的活动组合
     postageLis(  postageEntity){
        let res = new ArrayList ();
        let sukList2 = postageEntity.getSukList();

        let comparableCombination = new ComparableCombination(sukList2);
        let sukList = comparableCombination.findCombinations();
         sukList.forEach(dto => {
             let  postageEntity1 = ConvertUtils.sourceToTarget(postageEntity, PostageEntity.class);
             postageEntity1.setDmsPostageActivitiesRanges(postageEntity.getDmsPostageActivitiesRanges());
             postageEntity1.setSukList(dto);

             if(postageEntity1.totalPrice()){
                 res .add(postageEntity1);
             }
         })

        return  res;

    }



    //两个活动是否冲突 活动互斥
    activityMutex(  a ,  b){

        let sukList = a.getSukList();
       let  sukList1 = b.getSukList();


        sukList.forEach( suk =>{
            sukList1.forEach ( suk2 =>{
                if(suk.getId().equals(suk2.getId())){
                    return true ;
                }
            })
        })

        return  false;
    }


}
